from OWRpy import * 
import redRGUI 
from OWRpy import * 
import redRGUI 
import redRi18n
_ = redRi18n.get_(package = 'base')

class nortest(OWRpy): 
    globalSettingsList = ['commit']
    def __init__(self, **kwargs):
        OWRpy.__init__(self, **kwargs)
        
        # R code for generating plots
        self.R('source(\''+unicode(os.path.join(redREnviron.directoryNames['libraryDir'], 'normality', 'widgets', 'histNorm.R')).replace('\\', '//')+'\')')
        
        # Python variables
        self.data = {}
        self.RFunctionParam_object = ''

        #create R variables in the R session. 
        self.setRvariableNames(["uninormtest", "mvnormtest"])
        
        # Input
        self.inputs.addInput('id0', _('R Variable Object'), signals.base.RDataFrame, self.processobject)

        # GUI
        self.RFunctionParam_GUI_tabs = redRGUI.base.tabWidget(self.controlArea)
        self.RFunctionParam_GUI_tabsNorm = self.RFunctionParam_GUI_tabs.createTabPage(name = "Stats",orientation='vertical')
        self.RFunctionParam_GUI_tabsPlot = self.RFunctionParam_GUI_tabs.createTabPage(name = "Plot",orientation='vertical')
        
        self.testCategory = redRGUI.base.comboBox(self.RFunctionParam_GUI_tabsNorm,  label = "Test type: ",
        items = [('univariate','Univariate'),('multivariate','Multivariate')],
        editable=False, callback = self.onTestChange)

        self.testOptions = redRGUI.base.widgetBox(self.RFunctionParam_GUI_tabsNorm)

        # univar GUI
        self.univar = redRGUI.base.groupBox(self.testOptions, label='Options')
 
        self.namesListUni = redRGUI.base.listBox(self.univar, label = _('Select element'))
        self.namesListUni.setSelectionMode(QAbstractItemView.SingleSelection)

        self.methodButtonsUni = redRGUI.base.radioButtons(self.univar,  label = "Normality test", 
        buttons = [('Anderson-Darling'),
        ('Cramer-von Mises'),
        ('Lilliefors (Kolmogorov-Smirnov)'),
        ('Pearson chi-square'),
        ('Shapiro-Francia')],
        setChecked='Anderson-Darling',orientation='vertical')

        self.plotIt = redRGUI.base.checkBox(self.univar, label= 'Plot', buttons=['Normality','Q-Q plot'],
        setChecked=['Normality','Q-Q plot'],orientation='horizontal')
        
        # multivar GUI
        self.multivar = redRGUI.base.groupBox(self.testOptions, label='Options')
        self.namesListMulti = redRGUI.base.listBox(self.multivar, label = _('Select at least three elements'))
        self.namesListMulti.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.methodButtonsMulti = redRGUI.base.radioButtons(self.multivar,  label = "Normality test", 
        buttons = [('Shapiro-Wilk')],
        setChecked='Shapiro-Wilk',orientation='vertical')
        self.multivar.hide()
        
        self.RoutputWindow = redRGUI.base.textEdit(self.RFunctionParam_GUI_tabsNorm, label = _("RoutputWindow"))
        
        self.plotArea = redRGUI.plotting.redRPlot(self.RFunctionParam_GUI_tabsPlot, label = "Diagnostic plots")
        
        # Commit
        self.commit = redRGUI.base.commitButton(self.bottomAreaRight, _("Commit"), alignment=Qt.AlignLeft, 
        callback = self.commitFunction, processOnInput=True)
        
        
    def onTestChange(self):
        self.univar.hide()
        self.multivar.hide()
        if self.testCategory.currentId() == 'univariate':
            self.univar.show()
        elif self.testCategory.currentId() == 'multivariate':
            self.multivar.show()
        
    def processobject(self, data):
        if not self.require_librarys(["nortest"]):
            self.status.setText('R Libraries Not Loaded.')
            return
        if not self.require_librarys(["mvnormtest"]):
            self.status.setText('R Libraries Not Loaded.')
            return
        
        if data:
            self.RFunctionParam_object=data.getData()
            self.data = data
            self.namesListUni.update(self.R('names('+self.RFunctionParam_object+')', wantType = 'list'))
            self.namesListMulti.update(self.R('colnames('+self.RFunctionParam_object+')', wantType = 'list'))
            if self.commit.processOnInput():
                self.commitFunction()
        else:
            self.RFunctionParam_object=''

    def commitFunction(self):
        if self.testCategory.currentId() == 'univariate':
            if unicode(self.RFunctionParam_object) == '':
                self.status.setText('No data')
                return
            if len(self.namesListUni.selectedItems()) == 0:
                self.status.setText('Must select a column')
                return # must select a column.
        
            if 'Anderson-Darling' in self.methodButtonsUni.getChecked(): self.norTest='ad.test'
            if 'Cramer-von Mises' in self.methodButtonsUni.getChecked(): self.norTest='cvm.test'
            if 'Lilliefors (Kolmogorov-Smirnov)' in self.methodButtonsUni.getChecked(): self.norTest='lillie.test'
            if 'Pearson chi-square' in self.methodButtonsUni.getChecked(): self.norTest='pearson.test'
            if 'Shapiro-Francia' in self.methodButtonsUni.getChecked(): self.norTest='sf.test'        
            
            self.R('rSelected<-'+unicode(self.RFunctionParam_object)+'[,'+unicode(self.namesListUni.row(self.namesListUni.currentItem())+1)+']')
            self.R(self.Rvariables['uninormtest']+'<-'+self.norTest+'(x=rSelected)') 
            
            if self.plotIt.getChecked() == ['Q-Q plot','Normality'] :
                self.plotArea.plotMultiple(query = 'x=rSelected, main="Normality", col="lightgray"', function = 'bothNorm')
                #self.R('bothNorm(x=rSelected, main="Normality", col="lightgray")')
            elif self.plotIt.getChecked() == ['Normality'] :
                self.plotArea.plotMultiple(query = 'x=rSelected, main="Normality", col="lightgray"', function = 'histNorm')
                #self.R('histNorm(rSelected, main="Normality", col="lightgray")')
            elif self.plotIt.getChecked() == ['Q-Q plot'] :
                self.plotArea.plotMultiple(query = 'x=rSelected, main="Q-Q plot", col="lightgray"', function = 'QQNorm')
                #self.R('QQNorm(rSelected, main="Q-Q plot", col="lightgray")')
            
            self.RoutputWindow.clear()
            tmp = self.R('paste("<u>Data name</u>: ", '+self.Rvariables['uninormtest']+'$data.name,"\n", "<u>Method</u>: ",'+self.Rvariables['uninormtest']+'$method,"\n", "<u>Test statistic</u>: ", '+self.Rvariables['uninormtest']+'$statistic,"\n","<u>p-value</u>: ", '+self.Rvariables['uninormtest']+'$p.value, collapse ="\n")')
            self.RoutputWindow.insertHtml('<br><pre>'+tmp+'</pre>')
        
        elif self.testCategory.currentId() == 'multivariate': 
            if len(self.namesListMulti.selectedItems()) < 2: 
                self.status.setText('Select at least two items, or select "Univariate" for single variable normality test.')
                self.RoutputWindow.clear()
                tmp = "No results (see status text)."
                self.RoutputWindow.insertHtml('<br><pre>'+tmp+'</pre>')
                return
            else:
                self.status.setText('Data processing...')
            
            selectedDFItems = []
            for name in self.namesListMulti.selectedItems():
                selectedDFItems.append('"'+unicode(name)+'"') # get the text of the selected items
            
            injection = []
            
            if self.namesListMulti:
                self.R('rSelected<-as.data.frame('+self.RFunctionParam_object+'[colnames('+self.RFunctionParam_object+')'+' %in% c('+','.join(selectedDFItems)+')'+',drop = FALSE])', wantType = 'NoConversion')
                injection.append('rSelected')

            # combine all the parameters in the a string    
            inj = ','.join(injection)
                
            self.R('%s<-mshapiro.test(as.matrix(t(%s)))' % (self.Rvariables['mvnormtest'], inj), wantType = 'NoConversion')
            
            
            self.RoutputWindow.clear()
            tmp = self.R('paste("<u>Data name</u>: ", '+self.Rvariables['mvnormtest']+'$data.name,"\n", "<u>Method</u>: ",'+self.Rvariables['mvnormtest']+'$method,"\n", "<u>Test statistic</u>: ", '+self.Rvariables['mvnormtest']+'$statistic,"\n","<u>p-value</u>: ", '+self.Rvariables['mvnormtest']+'$p.value, collapse ="\n")')
            self.RoutputWindow.insertHtml('<br><pre>'+tmp+'</pre>')
        
        else:
            self.status.setText('Nothing has been done. Please check all parameters.')
